package com.example.dayu521.msg_sender.listener;

import com.example.dayu521.msg_sender.service.ISeckillSessionService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.example.dayu521.contants.RedisC;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

//FIXME 并发问题
//BUG 出错恢复
//FIXME 加锁也会因为分区问题而出错
//FIXME 数据库与redis之间的交互是通过服务集群来传输

//TODO 这里的任务发送,用服务端确认回调,明显应该使用协程,但java19并没有..

//@Service
//@Primary
@Slf4j
public class MyConfirmCallback implements RabbitTemplate.ConfirmCallback  {

    @Resource(name="redisTemplate")
    private RedisTemplate<String, Long> redisTemplate;

    @Configuration
    @ConditionalOnBean(MyConfirmCallback.class)
    public static class InitThis{
        public InitThis(MyConfirmCallback myConfirmCallback,ISeckillSessionService iSeckillSessionService){
            myConfirmCallback.setiSeckillSessionService(iSeckillSessionService);
        }
    }

    public void setiSeckillSessionService(ISeckillSessionService iSeckillSessionService) {
        this.iSeckillSessionService = iSeckillSessionService;
    }

    private ISeckillSessionService iSeckillSessionService;

    @Override
    public void confirm(CorrelationData correlationData, boolean b, String cause) {
        //这里只能确保每一个消息都被发送了,但不能确保每一个都被发送一次
        //因为确认消息收到和更改redis状态不是事务性操作
        if(b) {
            var i=redisTemplate.opsForValue().increment(RedisC.Shangjia.msg_sender_status);
            if(i%RedisC.Shangjia.msg_sender_batch_size==0){
                iSeckillSessionService.sync_send_msg();
            }
        }else{//如果发送失败,就换其他服务或线程尝试,避免网络问题
            log.warn("消息发送失败,原因:{}\n==>失败消息:{}",cause,correlationData.toString());
        }
    }
}
